package fhjoanneum.itm11.antesk.simplehack;
import java.util.*;

public class Map
{
	// Members -----------------------------------------------------------
	private Vector<Tile> tiles = new Vector<Tile>();
	private Config config = new Config("config.txt");
	private Config settings = new Config("settings.txt");
	private PlayerCharacter player_character;
		
	// Constructor -------------------------------------------------------
	public Map(){}
		
	// Methods ===========================================================
	
	// Getters and setters -----------------------------------------------
	public PlayerCharacter getPlayerCharacter(){
		return this.player_character;}
	public Vector<Tile> getTiles(){return tiles;}
	public Config getConfig(){return config;}

	// Builds the map ----------------------------------------------------
	public void createMap()
	{
		config.readFile();
				
		for(int i = 0; i < config.getHeight(); i++)
		{
			for(int j = 0; j < config.getWidth(); j++)
			{
				createTile(i, j);
				
				// Shortcuts
				Config s = settings;
				Vector<Tile> t = tiles;
				
				// Adding entities to the tiles
				if( t.indexOf(t.lastElement()) == 
						Integer.valueOf(s.readProperty("player_position")) )
				{
					t.elementAt(t.indexOf(t.lastElement())).
					setCharacter(player_character = 
					new PlayerCharacter(t.elementAt(t.indexOf(t.lastElement()))));
				}
				else if( s.parsePositions(s.readProperty("goblin_position")).
								 contains(t.indexOf(t.lastElement())) )
				{
					t.elementAt(t.indexOf(t.lastElement())).
					setCharacter(new GoblinCharacter(t.elementAt(t.indexOf(t.lastElement()))));
				}
				else if( s.parsePositions(s.readProperty("small_potion_position")).
								 contains(t.indexOf(t.lastElement())) )
				{
					t.elementAt(t.indexOf(t.lastElement())).
					setItem(new ItemSmallPotion());
				}
				else if( s.parsePositions(s.readProperty("fire_trap_position")).
						 contains(t.indexOf(t.lastElement())) )
				{
					t.elementAt(t.indexOf(t.lastElement())).
					setEvent(new FiretrapEvent());
				}
			}
		}

		linkTiles();
	}
	
	// Fills tiles accordingly -------------------------------------------
	public void createTile(int height, int width)
	{
		if(config.getMap()[height][width] == '1')
		{
			tiles.add(new WallTile());
		}
		else if(this.config.getMap()[height][width] == '2')
		{
			tiles.add(new DoorTile());
		}
		else
		{
			tiles.add(new Tile());
		}
	}
	
	/**
	 * Assigns each Tile a neighboring one according to logical
	 * conditions. Only assigns neighbors if they can exist.
	 */
	private void linkTiles()
	{
		// North neighbors
		Iterator<Tile> north_iterator = tiles.iterator();
		for(int i = 0; i < tiles.size(); i++)
		{
			if(i < config.getWidth())
			{
				north_iterator.next().setNeighbor(null, Direction.NORTH);
			}
			else
			{
				north_iterator.next().setNeighbor(tiles.
						elementAt(i - config.getWidth()),	Direction.NORTH);
			}
		}
		
		// West neighbor
		Iterator<Tile> west_iterator = tiles.iterator();
		for(int i = 0; i < tiles.size(); i++)
		{
			if(i % config.getWidth() == 0)
			{
				west_iterator.next().setNeighbor(null, Direction.WEST);
			}
			else
			{
				west_iterator.next().setNeighbor(tiles.elementAt(i - 1), 
						Direction.WEST);
			}
		}
		
		// East neighbor
		Iterator<Tile> east_iterator = tiles.iterator();
		for(int i = 0; i < tiles.size(); i++)
		{
			if(i % config.getWidth() == config.getWidth() - 1)
			{
				east_iterator.next().setNeighbor(null, Direction.EAST);
			}
			else
			{
				east_iterator.next().setNeighbor(tiles.elementAt(i + 1), 
						Direction.EAST);
			}
		}
		
		// South neighbors
		Iterator<Tile> south_iterator = tiles.iterator();
		for(int i = 0; i < tiles.size(); i++)
		{
			if(i > (config.getWidth() * (config.getHeight() - 1)) - 1)
			{
				south_iterator.next().setNeighbor(null, Direction.SOUTH);
			}
			else
			{
				south_iterator.next().setNeighbor
					(tiles.elementAt(i + config.getWidth()),	Direction.SOUTH);
			}
		}
	}
	
	/**
	 * Prints the current map state in the console.
	 * 
	 * @deprecated This command will be replaced by the graphical output
	 * 						 once it is completed.
	 */
	public void printMap()
	{
		Iterator<Tile> current_tile = tiles.iterator();
		
		while(current_tile.hasNext())
		{
			for(int x = 0; x < config.getHeight(); x++)
			{
				for(int y = 0; y < config.getWidth(); y++)
				{
					Tile nexttile = current_tile.next();
					Character character = nexttile.getCharacter();
					
					if(character == null && nexttile.getItem() == null && 
							nexttile.getEvent() == null) // no char, item or event
					{
						// Door test -----------------------------------------------
						if(nexttile.getTileType() == TileType.DOOR) // is door
						{
							DoorTile next_doortile = (DoorTile) nexttile;
							
							if(next_doortile.getOpened() == true) // is opened
							{
								System.out.print(next_doortile.getTestOpen());
							}
							else if(next_doortile.getOpened() == false) // is closed
							{
								System.out.print(next_doortile.getTest());
							}
						}
						else
						{
							System.out.print(nexttile.getTest()); // not door
						}
						// Door test end -------------------------------------------
					}
					else if(nexttile.getCharacter() != null) // character
					{
						System.out.print(character.getTest());
					}
					else if(nexttile.getItem() != null) // item
					{
						System.out.print(nexttile.getItem().getTest());
					}
					else if(nexttile.getEvent() != null) // event
					{
						// Warning for event - REMOVE BEFORE FINAL!
						System.out.print(nexttile.getEvent().getTest());
						/*
							This should only be shown in the final version if the
						 	player has the ability to detect traps. Implementation
						  pending. 
						*/
					}
				}
				System.out.println(); // new line
			}
		}
	}
}
